﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SymmetricEncription.Controls
{
    /// <summary>
    /// Interaction logic for BinView.xaml
    /// </summary>
    public partial class BinView : UserControl
    {
        public static readonly DependencyProperty RowsProperty =
                    DependencyProperty.Register("Rows", typeof(int), typeof(BinView), new FrameworkPropertyMetadata(1, new PropertyChangedCallback(OnRowsChanged)));
        public int Rows
        {
            get { return (int)GetValue(RowsProperty); }
            set { SetValue(RowsProperty, value); }
        }
        private static void OnRowsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            BinView invoker = sender as BinView;
            if (invoker != null)
            {
                int newValue = (int)e.NewValue;
                int oldValue = (int)e.OldValue;
                invoker.OnRowsChanged(newValue, oldValue);
            }
        }
        private void OnRowsChanged(int newValue, int oldValue)
        {
            RecreateView();
        }

        public static readonly DependencyProperty ColumnsProperty =
                    DependencyProperty.Register("Columns", typeof(int), typeof(BinView), new FrameworkPropertyMetadata(-1, new PropertyChangedCallback(OnColumnsChanged)));
        public int Columns
        {
            get { return (int)GetValue(ColumnsProperty); }
            set { SetValue(ColumnsProperty, value); }
        }
        private static void OnColumnsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            BinView invoker = sender as BinView;
            if (invoker != null)
            {
                int newValue = (int)e.NewValue;
                int oldValue = (int)e.OldValue;
                invoker.OnColumnsChanged(newValue, oldValue);
            }
        }
        private void OnColumnsChanged(int newValue, int oldValue)
        {
            RecreateView();
        }

        public static readonly DependencyProperty DataProperty =
                    DependencyProperty.Register("Data", typeof(byte[]), typeof(BinView), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnDataChanged)));
        public byte[] Data
        {
            get { return (byte[])GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }
        private static void OnDataChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            BinView invoker = sender as BinView;
            if (invoker != null)
            {
                byte[] newValue = (byte[])e.NewValue;
                byte[] oldValue = (byte[])e.OldValue;
                invoker.OnDataChanged(newValue, oldValue);
            }
        }
        private void OnDataChanged(byte[] newValue, byte[] oldValue)
        {
            RecreateView();
        }


        private void RecreateView()
        {
            try
            {
                this.gridMain.RowDefinitions.Clear();
                this.gridMain.ColumnDefinitions.Clear();
                this.gridMain.Children.Clear();

                int rows = this.Rows;
                int columns = this.Columns;
                byte[] data = this.Data;

                if (data != null && data.Length > 0)
                {
                    if (rows < 0 && columns < 0)
                    {
                        rows = (int)Math.Round(Math.Sqrt(data.Length));
                        columns = (int)Math.Ceiling(((double)data.Length) / rows);
                    }
                    else if (rows < 0)
                    {
                        rows = (int)Math.Ceiling(((double)data.Length) / columns);
                    }
                    else if (columns < 0)
                    {
                        columns = (int)Math.Ceiling(((double)data.Length) / rows);
                    }

                    if (columns > 0 && rows > 0)
                    {
                        for (int i = 0; i < rows; i++)
                        {
                            this.gridMain.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
                        }
                        for (int i = 0; i < columns; i++)
                        {
                            this.gridMain.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
                        }
                        for (int i = 0; i < data.Length; i++)
                        {
                            var border = new Border()
                            {
                                Background = i % 2 == 0 ? Brushes.LightBlue : Brushes.LightGray,
                            };
                            var textBlock = new TextBlock()
                            {
                                Text = data[i].ToString("X2"),
                                VerticalAlignment = VerticalAlignment.Center,
                                HorizontalAlignment = HorizontalAlignment.Center,
                                TextAlignment = TextAlignment.Center,
                                Margin = new Thickness(3),
                            };
                            border.Child = textBlock;
                            Grid.SetColumn(border, i % columns);
                            Grid.SetRow(border, i / columns);
                            this.gridMain.Children.Add(border);
                        }
                    }
                }
            }
            catch
            {
            }
        }

        public BinView()
        {
            InitializeComponent();
        }
    }
}
